/**
 * @author 王琪 <wangqi@huizhaofang.com>
 * @since 2020-03-08
 */
package com.diploma.project.aiqiyi.service;

import com.diploma.project.aiqiyi.common.enums.CommonOutputEnum;
import com.diploma.project.aiqiyi.dao.UserVideoDao;
import com.diploma.project.aiqiyi.dao.VideoDao;
import com.diploma.project.aiqiyi.dto.VideoDetailDto;
import com.diploma.project.aiqiyi.exception.BusinessException;
import com.diploma.project.aiqiyi.model.User;
import com.diploma.project.aiqiyi.model.UserVideo;
import com.diploma.project.aiqiyi.model.Video;
import com.diploma.project.aiqiyi.utils.SqlParamUtil;
import com.diploma.project.aiqiyi.utils.StringUtil;
import com.google.common.collect.Lists;
import com.google.gson.internal.$Gson$Types;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
public class VideoService {

    @Autowired
    private VideoDao videoDao;
    @Autowired
    private UserVideoDao userVideoDao;


    @Lazy
    @Autowired
    private UserService userService;
    @Autowired
    private HttpServletRequest httpServletRequest;
    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    public List<Video> queryVideosByCategory(Integer category) {
        if (category > 0 && category!=8)
            return videoDao.select(Video.builder().category(category).build());

        if(category ==8) {
            Byte a = 1;
            return queryVideosByType(a);
        }

        // 推荐
        if (category <= 0) {
            try {
                userService.checkUser();
            } catch (Exception e) {
                log.error("检查用户登录失败, {}", e.getMessage());
            }
            if (category == 0)
                return queryRecommendVideos(50);
            if (category == -1) {
                User user = (User) httpServletRequest.getAttribute("user");
                if (user != null)
                    return queryUserVideos(2);
                else
                    throw new BusinessException(CommonOutputEnum._4043);
            }
        }

        return Lists.newArrayList();
    }

    public List<Video> queryVideosByType(Byte type){
        if(type == 1)
            return videoDao.select(Video.builder().type(type).build());
        return Lists.newArrayList();
    }

    public void saveUserVideo(Integer id, Integer type, String beizhu) {
        User user = (User) httpServletRequest.getAttribute("user");
        String deviceId = httpServletRequest.getHeader("deviceId");

        Example example = new Example(UserVideo.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("type", type);
        criteria.andEqualTo("videoId", id);
        criteria.andEqualTo("beizhu", beizhu);
        UserVideo.UserVideoBuilder builder = UserVideo.builder().type(type).videoId(id).beizhu(beizhu);
        if (user != null) {
            builder.userId(user.getId());
            criteria.andEqualTo("userId", user.getId());
        } else {
            criteria.andEqualTo("deviceId", deviceId);
            criteria.andIsNull("userId");
        }

        List<UserVideo> uvs = userVideoDao.selectByExample(example);
        builder.deviceId(deviceId);
        UserVideo uv = null;
        if (!uvs.isEmpty())
            uv = uvs.get(0);

        if (uv == null || (uv.getUserId() != null && (user != null && !uv.getUserId().equals(user.getId())
                || user == null))) {
            userVideoDao.insertSelective(builder.build());
            return;
        }

        if (type == 2 && uv != null) {
            userVideoDao.deleteByPrimaryKey(uv.getId());
        }


        userVideoDao.updateByPrimaryKeySelective(UserVideo.builder().id(uv.getId())
                .deviceId(deviceId)
                .userId(user == null ? null : user.getId())
                .createTime(new Date()).build());
    }

    public VideoDetailDto queryVideoDetail(Integer id) {
        Video video = videoDao.selectByPrimaryKey(id);
        VideoDetailDto dto = VideoDetailDto.builder().build();
        BeanUtils.copyProperties(video, dto);

        // 查询是否已收藏，是否已购买
        try {
            userService.checkUser();
        } catch (Exception e) {
            log.error("检查用户登录失败, {}", e.getMessage());
        }
        User user = (User) httpServletRequest.getAttribute("user");
        if (user != null) {
            UserVideo condition = UserVideo.builder().userId(user.getId())
                    .videoId(id)
                    .build();
            userVideoDao.select(condition).forEach(uv -> {
                if (uv.getType() == 2)
                    dto.setIsRecommend(1);
                if (uv.getType() == 3)
                    dto.setIsBuy(1);
            });
        }

        dto.setRecommendVideos(queryRecommendVideos(10));

        return dto;
    }

    public List<Video> queryUserVideos(Integer type) {
        User user = (User) httpServletRequest.getAttribute("user");
        return videoDao.selectUserVideos(user.getId(), null, type);
    }

    //评论
    public List<UserVideo> queryRemark(Integer id){
        User user = (User) httpServletRequest.getAttribute("user");
        Example example1 = new Example(UserVideo.class);
        example1.createCriteria().andEqualTo("videoId",id)
                .andEqualTo("type",4);
        return userVideoDao.selectByExample(example1);

    }

    public void saveUserVideoHistory(User user) {
        String deviceId = httpServletRequest.getHeader("deviceId");

        Example example = new Example(UserVideo.class);
        example.createCriteria().andEqualTo("deviceId", deviceId)
                .andIsNull("userId").andEqualTo("type", 1);
        userVideoDao.selectByExample(example).forEach(uv -> {
            UserVideo existUv = userVideoDao.selectOne(UserVideo.builder().userId(user.getId()).type(1).videoId(uv.getVideoId()).build());
            if (existUv != null) {
                userVideoDao.updateByPrimaryKeySelective(UserVideo.builder()
                        .createTime(uv.getCreateTime()).deviceId(uv.getDeviceId()).id(existUv.getId()).build());
                userVideoDao.deleteByPrimaryKey(uv.getId());
            } else {
                userVideoDao.updateByPrimaryKeySelective(UserVideo.builder()
                        .userId(user.getId()).id(uv.getId()).build());
            }
        });
    }

    private List<Video> queryRecommendVideos(Integer limit) {
        User user = (User) httpServletRequest.getAttribute("user");
        String deviceId = httpServletRequest.getHeader("deviceId");

        List<Video> cacheVideo = null;
        if (user != null) {
            cacheVideo = videoDao.selectUserVideos(user.getId(), null, 1);
        } else if (StringUtil.isNoneBlank(deviceId)) {
            cacheVideo = videoDao.selectUserVideos(null, deviceId, 1);
        } else {
            cacheVideo = Lists.newArrayList();
        }

        // 随机抽取返回
        if (cacheVideo.isEmpty())
            return videoDao.selectByRandom(limit);

        // 无脑推荐：抽取出现次数最多的关键字，数量不足补充第二多的，依次类推，直到达到指定数量
        List<String> keywords = Lists.newArrayList();
        cacheVideo.stream().forEach(item -> {
            if (StringUtil.isNoneBlank(item.getTag()))
                keywords.addAll(Arrays.asList(item.getTag().split(",")));
        });
        Map<String, Long> groupByKey =
                keywords.stream().collect(Collectors.groupingBy(item -> item, Collectors.counting()));

        List<Map.Entry<String, Long>> list = new ArrayList(groupByKey.entrySet());
        Collections.sort(list, (o1, o2) -> (int) (o2.getValue() - o1.getValue()));

        List<Video> result = Lists.newArrayList();
        outter:
        for (Map.Entry<String, Long> entry : list) {
            Example example = new Example(Video.class);
            example.createCriteria().andLike("tag", SqlParamUtil.getBetweenLike(entry.getKey()));
            cacheVideo = videoDao.selectByExample(example);

            inner:
            for (Video video : cacheVideo) {
                if (!checkDuplication(video, result)) {
                    result.add(video);
                    if (result.size() == limit) {
                        break outter;
                    }
                }
            }
        }
        return result;
    }

    private boolean checkDuplication(Video item, List<Video> result) {
        for (Video video : result) {
            if (video.getId().equals(item.getId()))
                return true;
        }
        return false;
    }

    public List<Video> queryVideos(String keyword) {
        if (StringUtil.isBlank(keyword))
            return Lists.newArrayList();

        Example example = new Example(Video.class);
        example.createCriteria().orLike("title", SqlParamUtil.getBetweenLike(keyword))
                .orLike("tag", SqlParamUtil.getBetweenLike(keyword));
        return videoDao.selectByExample(example);
    }

    public void deleteUserHistory() {
        User user = (User) httpServletRequest.getAttribute("user");
        Example example = new Example(UserVideo.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("type", 1);
        criteria.andEqualTo("userId", user.getId());
        userVideoDao.deleteByExample(example);
    }
}
